package com.meilai.project.service.system.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.constant.MessageCenterTypeEnum;
import com.meilai.project.dto.system.MessageCenterRouterProps;
import com.meilai.project.dto.system.MessageCenterSearchDTO;
import com.meilai.project.entity.system.MessageCenter;
import com.meilai.project.entity.workflow.WFData;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.system.MessageCenterMapper;
import com.meilai.project.mapper.system.UserRoleRelationMapper;
import com.meilai.project.mapper.workflow.WorkFlowDefaultMapper;
import com.meilai.project.service.system.MessageCenterService;
import com.meilai.project.service.workflow.WFDataService;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.vo.workflow.WorkFlowTypeNameAndRouterVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 张驰
 * @since 2022-04-15
 */
@Service
public class MessageCenterServiceImpl extends ServiceImpl<MessageCenterMapper, MessageCenter> implements MessageCenterService {

    @Autowired
    private UserRoleRelationMapper userRoleRelationMapper;
    @Autowired
    private WorkFlowDefaultMapper workFlowDefaultMapper;
    @Autowired
    private WFDataService wfDataService;

    private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Override
    public Page<MessageCenter> selectPageList(Integer current_page, Integer page_size, MessageCenterSearchDTO searchDTO) {
        searchDTO.setUser_id(ThreadLocalUserUtil.get().getId());
        Page<MessageCenter> page = new Page<MessageCenter>(current_page, page_size);
        List<MessageCenter> list = baseMapper.selectPageList(page, searchDTO);
        return page.setRecords(list);
    }

    @Override
    @Transactional
    public boolean setHasReadByIds(List<Long> ids) {
        if(CollectionUtils.isEmpty(ids)) throw new CommonException("消息ids不得为空!");
        update(new UpdateWrapper<MessageCenter>().set("read_at", LocalDateTime.now()).in("id", ids));
        return true;
    }

    @Override
    public int getOwnUnReadCount() {
        return baseMapper.getOwnUnReadCount(ThreadLocalUserUtil.get().getId());
    }

    /**
     * 生成“系统”类型消息
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     */
    @Override
    @Transactional
    public void genSysMessage(Long user_id, String title, String content) {
        assembleRouterMessage(MessageCenterTypeEnum.SYSTEM.getType(), user_id, title, content);
    }

    /**
     * 生成“审批”、"抄送"类型消息
     * @param user_id 用户id
     * @param flow_type 标题
     * @param wf_data_id 流程id
     * @param data_id 数据id
     * @param msgType 审批类型（1待审，通知审批人  2通过，提醒提交人  3退回，通知提交人）
     *                抄送类型（4抄送，通知传阅人）
     */
    @Override
    @Transactional
    public void genFlowMessage(Long user_id, Integer flow_type, Long wf_data_id, Long data_id, Integer msgType) {
        MessageCenter mc = new MessageCenter();
        mc.setUser_id(user_id);
        mc.setCreated_at(LocalDateTime.now());
        mc.setFlow_type(flow_type);
        mc.setWf_data_id(wf_data_id);
        mc.setData_id(data_id);

        WorkFlowTypeNameAndRouterVO wfVO = workFlowDefaultMapper.getTypeNameAndRouterByType(flow_type);
        String to_router_name = wfVO.getRouter();
        if(StringUtils.isNotEmpty(to_router_name)){
            // 校验user_id是否有这个路由权限
            if(userRoleRelationMapper.userHasRouter(user_id, to_router_name) > 0) mc.setTo_router_name(to_router_name);
        }

        WFData wfData = wfDataService.getById(wf_data_id);
        String title = "《"+wfData.getTitle()+"》";
        StringBuilder sb = new StringBuilder();
        switch (msgType){
            case 1: title+="待审批";
                    mc.setType(MessageCenterTypeEnum.CHECK.getType());
                    mc.setFlow_status(1);
                    sb.append("当前节点：").append(wfData.getNode_name()).append("<br/>")
                            .append("提交人：").append(wfData.getApplyer_name()).append("<br/>")
                            .append("提交时间：").append(sdf.format(wfData.getCreate_at()));
                    break;
            case 2: title+="已通过";
                    mc.setType(MessageCenterTypeEnum.CHECK.getType());
                    mc.setFlow_status(2);
                    sb.append("当前节点：已通过<br/>").append("通过时间：").append(sdf.format(wfData.getFlow_at()));
                    break;
            case 3: title+="被退回";
                    mc.setType(MessageCenterTypeEnum.CHECK.getType());
                    mc.setFlow_status(3);
                    sb.append("当前节点：被退回<br/>").append("退回时间：").append(sdf.format(wfData.getFlow_at()));
                    break;
            case 4: title+="待传阅";
                    mc.setType(MessageCenterTypeEnum.COPY.getType());
                    sb.append("当前节点：").append(wfData.getNode_name()).append("<br/>")
                            .append("最新审批：").append(sdf.format(wfData.getFlow_at()));
                    break;
        }
        mc.setTitle(title);
        mc.setContent(sb.toString());
        save(mc);
    }

    /**
     * 生成“任务”类型消息
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     * @param to_router_name 需要跳转的路由
     * @param params 需要跳转的路由参数
     */
    @Override
    @Transactional
    public void genMissionMessage(Long user_id, String title, String content, String to_router_name, Map<String, String> params) {
        assembleRouterMessage(MessageCenterTypeEnum.MISSION.getType(), user_id, title, content, new MessageCenterRouterProps(to_router_name, params));
    }

    /**
     * 生成“提醒”类型消息
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     * @param to_router_name 需要跳转的路由
     * @param params 需要跳转的路由参数
     */
    @Override
    @Transactional
    public void genTipMessage(Long user_id, String title, String content, String to_router_name, Map<String, String> params) {
        assembleRouterMessage(MessageCenterTypeEnum.TIP.getType(), user_id, title, content, new MessageCenterRouterProps(to_router_name, params));
    }

    /**
     * 生成“推送”类型消息
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     * @param to_router_name 需要跳转的路由
     * @param params 需要跳转的路由参数
     */
    @Override
    @Transactional
    public void genPushMessage(Long user_id, String title, String content, String to_router_name, Map<String, String> params) {
        assembleRouterMessage(MessageCenterTypeEnum.PUSH.getType(), user_id, title, content, new MessageCenterRouterProps(to_router_name, params));
    }

    /**
     * 生成“其他”类型消息
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     */
    @Override
    @Transactional
    public void genOtherMessage(Long user_id, String title, String content) {
        assembleRouterMessage(MessageCenterTypeEnum.OTHER.getType(), user_id, title, content);
    }

    /**
     * 组装含路由的消息
     * @param type 类型
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     */
    private void assembleRouterMessage(Integer type, Long user_id, String title, String content) {
        MessageCenter mc = new MessageCenter();
        mc.setType(type);
        mc.setUser_id(user_id);
        mc.setTitle(title);
        mc.setContent(content);
        mc.setCreated_at(LocalDateTime.now());
        save(mc);
    }

    /**
     * 组装含路由的消息
     * @param type 类型
     * @param user_id 用户id
     * @param title 标题
     * @param content 内容，可拼接为html
     * @param routerProps 跳转路由的配置
     */
    private void assembleRouterMessage(Integer type, Long user_id, String title, String content, MessageCenterRouterProps routerProps) {
        MessageCenter mc = new MessageCenter();
        mc.setType(type);
        mc.setUser_id(user_id);
        mc.setTitle(title);
        mc.setContent(content);
        if(routerProps.getType() == 1){
            String routerName = routerProps.getName();
            Map<String, String> params = routerProps.getParams();
            // 校验user_id是否有这个路由权限
            if(userRoleRelationMapper.userHasRouter(user_id, routerName) > 0) {
                mc.setTo_router_name(routerName);
                if(params != null && !params.isEmpty()){
                    JSONObject _params = new JSONObject();
                    for (Map.Entry<String, String> entry : params.entrySet()) {
                        _params.put(entry.getKey(), entry.getValue());
                    }
                    if(!_params.isEmpty()) mc.setTo_router_params(_params.toJSONString());
                }
            }
        }
        if(routerProps.getType() == 2){
            String routerPath = routerProps.getPath();
            Map<String, String> variables = routerProps.getVariables();
            Map<String, String> querys = routerProps.getQuerys();
            if(variables != null && !variables.isEmpty()){
                JSONObject _variables = new JSONObject();
                List<String> querysStr = new ArrayList<>();
                for (Map.Entry<String, String> entry : variables.entrySet()) {
                    querysStr.add(entry.getKey()+"="+entry.getValue());
                }
                if(CollectionUtils.isNotEmpty(querysStr)){
                    routerPath = routerPath + "?" + String.join("&", querysStr);
                }
                mc.setTo_router_path(routerPath);
            }
            if(querys != null && !querys.isEmpty()){
                JSONObject _querys = new JSONObject();
                for (Map.Entry<String, String> entry : querys.entrySet()) {
                    _querys.put(entry.getKey(), entry.getValue());
                }
                if(!_querys.isEmpty()) mc.setTo_router_querys(_querys.toJSONString());
            }
        }
        mc.setCreated_at(LocalDateTime.now());
        save(mc);
    }
}
